package com.hlkj.pay.app.adminuser.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.adminuser.IPermissionAppService;
import com.hlkj.pay.app.adminuser.IRoleAppService;
import com.hlkj.pay.app.adminuser.IUserPermissionAppService;
import com.hlkj.pay.common.AdminUserResultCode;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.dto.admin.PermissionQueryDto;
import com.hlkj.pay.dto.admin.RoleQueryDto;
import com.hlkj.pay.enums.AdminUserEnum;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.infrastructure.model.admin.PermissionDO;
import com.hlkj.pay.infrastructure.model.admin.RoleDO;
import com.hlkj.pay.infrastructure.model.admin.RolePermissionMappingDO;
import com.hlkj.pay.service.admin.IAdminUserService;
import com.hlkj.pay.service.admin.IPermissionService;
import com.hlkj.pay.service.admin.IRoleService;
import com.hlkj.pay.service.common.IBusinessLogService;
import com.hlkj.pay.util.PermissionCoverUtils;
import com.hlkj.pay.vo.admin.req.user.MenuPageQueryReq;
import com.hlkj.pay.vo.admin.resp.menu.RoleDetailMenuResp;
import com.hlkj.pay.vo.admin.resp.menu.RoleDetailPermissionResp;
import com.hlkj.pay.vo.admin.resp.permission.PermissionDetailResp;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
 * @author HlpayTeam
 * @date 2024/09/18 16:30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PermissionAppServiceImpl implements IPermissionAppService {
	private final IPermissionService permissionService;
	private final IAdminUserService userService;
	private final IRoleService roleService;
	private final IBusinessLogService businessLogService;
	private final IUserPermissionAppService userPermissionAppService;
	private final IRoleAppService roleAppService;
	@Override
	public List<RoleDetailMenuResp> queryPermission(MenuPageQueryReq menuPageQueryReq) {
		PermissionQueryDto permissionQueryDto =new PermissionQueryDto();
		if(menuPageQueryReq.getSysType()==null){
			permissionQueryDto.setSysType(LocalContext.get().getSysType());
		}else {
			permissionQueryDto.setSysType(menuPageQueryReq.getSysType());
		}

		if(CollUtil.isNotEmpty(menuPageQueryReq.getRoleCode())){
			// 角色查询
			RoleQueryDto roleQueryDto = new RoleQueryDto();
			roleQueryDto.setCodeList(menuPageQueryReq.getRoleCode());
			List<RoleDO> roleList = roleService.queryRoleList(roleQueryDto);
			boolean admin = false;
			List<String> roleCodes = new ArrayList<>();
			if(CollUtil.isNotEmpty(roleList)){
				for(RoleDO role:roleList){
					roleCodes.add(role.getCode());
				}
				// 判断是否含有管理员权限
				admin = roleAppService.isAdmin(roleCodes,permissionQueryDto.getSysType());
			}
			// 非管理员
			if(!admin){
				List<RolePermissionMappingDO>  permissionMappingList = roleService.queryPermissionCodeByRoleCode(roleCodes);
				List<String> finalPermissionMappingList = permissionMappingList.stream().map(RolePermissionMappingDO::getPermissionCode).collect(Collectors.toList());
				if(CollUtil.isNotEmpty(finalPermissionMappingList)){
					permissionQueryDto.setPermissionCodeList(finalPermissionMappingList);
				}
			}
		}
		List<PermissionDO> permissionList = permissionService.queryPermissionList(permissionQueryDto);
		return  PermissionCoverUtils.permissionMenuList(permissionList);
	}
	@Override
	public PageResult<RoleDetailMenuResp> queryPermissionPage(MenuPageQueryReq menuPageQueryReq) {
		PageResult<RoleDetailMenuResp> pageResult=new PageResult<>();
		PermissionQueryDto permissionQueryDto =new PermissionQueryDto();
		if(menuPageQueryReq.getSysType()==null){
			permissionQueryDto.setSysType(LocalContext.get().getSysType());
		}else {
			permissionQueryDto.setSysType(menuPageQueryReq.getSysType());
		}
		permissionQueryDto.setPageNo(menuPageQueryReq.getPageNo());
		permissionQueryDto.setPageSize(menuPageQueryReq.getPageSize());
		permissionQueryDto.setRoot(true);
		PageResult<PermissionDO> permissionPage = permissionService.queryPermissionPage(permissionQueryDto);
		List<PermissionDO> modelList = permissionPage.getList();
		pageResult.setTotal(permissionPage.getTotal());
		pageResult.setPages(permissionPage.getPages());
		pageResult.setPageNo(permissionPage.getPageNo());
		pageResult.setPageSize(permissionPage.getPageSize());
		if(CollectionUtils.isEmpty(modelList)){
			return pageResult;
		}
		
		List<String> organizationCodes = modelList.stream()
				.map(permissionDO -> permissionDO.getCode()).collect(Collectors.toList());
		
		PermissionQueryDto organizationQuery = new PermissionQueryDto();
		organizationQuery.setSysType(permissionQueryDto.getSysType());
		organizationQuery.setNotInCode(organizationCodes);
		organizationQuery.setRoot(false);

		List<PermissionDO> childOrganizationList = permissionService.queryPermissionList(organizationQuery);
		modelList.addAll(childOrganizationList);
		pageResult.setList(PermissionCoverUtils.permissionMenuList(modelList));
		return pageResult;
	}
	@Override
	public CommonResult<PermissionDetailResp> queryPermissionDetail(String code) {
		PermissionDO permissionDO = permissionService.queryPermissionByCode(code);
		if(permissionDO==null){
			return CommonResult.success();
		}
		PermissionDetailResp permissionDetailResp=new RoleDetailPermissionResp();
		BeanUtils.copyProperties(permissionDO,permissionDetailResp);
		permissionDetailResp.processMeta();
		return CommonResult.success(permissionDetailResp);
	}
	@Override
	public CommonResult<String> addPermission(PermissionDetailResp permissionDetailReq) {
		log.info("addPermission permissionDetailReq:{}", JsonUtils.toJsonString(permissionDetailReq));
		if(StringUtils.hasText(permissionDetailReq.getName())){
			PermissionDO permissionDO = permissionService.queryParentPermissionByName(permissionDetailReq.getName(),permissionDetailReq.getType(),permissionDetailReq.getSysType());
			if(permissionDO!=null){
				return CommonResult.error(AdminUserResultCode.MENU_DOES_EXIST);
			}
		}
		PermissionDO queryMaxPermission=null;
		if(StringUtils.hasText(permissionDetailReq.getParentCode())){
			queryMaxPermission = permissionService.queryMaxPermission(permissionDetailReq.getParentCode(),null);
		}else {
			queryMaxPermission = permissionService.queryMaxPermission("",null);
		}

		String code=null;
		if(queryMaxPermission==null){
			if(!StringUtil.isEmpty(permissionDetailReq.getParentCode())){
				code=permissionDetailReq.getParentCode()+"01";
			}else {
				code="01";
			}
		}else {
			String permissionCode = queryMaxPermission.getCode();
			int lastCode = Integer.parseInt(permissionCode.substring(permissionCode.length() - 2, permissionCode.length()));
			if(!StringUtil.isEmpty(permissionDetailReq.getParentCode())){
				code=permissionDetailReq.getParentCode()+String.format("%02d", lastCode + 1);
			}else {
				code=String.format("%02d", lastCode + 1);
			}
		}
		PermissionDO permissionDO=new PermissionDO();
		BeanUtils.copyProperties(permissionDetailReq,permissionDO);
		permissionDO.setCode(code);
		permissionDO.setMetaInfo(JsonUtils.toJsonString(permissionDetailReq.getMeta()));
		if(permissionDetailReq.getSysType()==null){
			permissionDO.setSysType(LocalContext.get().getSysType());
		}else {
			permissionDO.setSysType(permissionDetailReq.getSysType());
		}
		permissionService.add(permissionDO);
		return CommonResult.success(permissionDO.getCode());
	}
	@Override
	public CommonResult<Void> updatePermission(PermissionDetailResp permissionDetailReq) {
		log.info("updatePermission permissionDetailReq:{}", JsonUtils.toJsonString(permissionDetailReq));
		PermissionDO permissionDO = permissionService.queryPermissionByCode(permissionDetailReq.getCode());
		if(permissionDO==null){
			return CommonResult.error(AdminUserResultCode.MENU_DOES_NOT_EXIST);
		}
		if(StringUtils.hasText(permissionDetailReq.getName())){
			PermissionDO existPermissionDO = permissionService.queryParentPermissionByName(permissionDetailReq.getName(),permissionDetailReq.getType(),permissionDetailReq.getSysType());
			if(existPermissionDO!=null&&!existPermissionDO.getCode().equals(permissionDetailReq.getCode())){
				return CommonResult.error(AdminUserResultCode.MENU_DOES_EXIST);
			}
		}
		PermissionDO updatePermissionDO=new PermissionDO();
		BeanUtils.copyProperties(permissionDetailReq,updatePermissionDO);
		updatePermissionDO.setId(permissionDO.getId());
		updatePermissionDO.setMetaInfo(JsonUtils.toJsonString(permissionDetailReq.getMeta()));
		updatePermissionDO.setSysType(permissionDO.getSysType());
		permissionService.update(updatePermissionDO);
		List<RolePermissionMappingDO> rolePermissionMappingList = roleService.queryPermissionCodeByPermissionCode(
				permissionDetailReq.getCode());
		//对应用户进行登出处理
		if(!CollectionUtils.isEmpty(rolePermissionMappingList)){
			rolePermissionMappingList.stream().forEach(rolePermissionMappingDO -> {
				List<Long> userIds=userService.roleChangeUser(rolePermissionMappingDO.getRoleCode(),false);
				userIds.stream().forEach(userId->{
					userPermissionAppService.authorityChange(userId);
				});
			});
		}
		//变更日志
		businessChangeLog(permissionDO,updatePermissionDO);
		return CommonResult.success();
		
	}
	@Override
	public CommonResult<Void> deletePermission(String permissionCode) {
		log.info("deletePermission permissionCode:{}", permissionCode);
		if(!StringUtils.hasText(permissionCode)){
			return CommonResult.error(CommonResultCode.PARAMETER_MISSING);
		}
		PermissionDO permissionDO = permissionService.queryPermissionByCode(permissionCode);
		if(permissionDO==null){
			return CommonResult.error(AdminUserResultCode.MENU_DOES_NOT_EXIST);
		}
		PermissionDO childOne = permissionService.queryParentPermission(permissionDO.getCode());
		if(childOne!=null){
			return CommonResult.error(AdminUserResultCode.MENU_CHILD_EXIST);
		}
		permissionService.delete(permissionDO.getId(),permissionDO.getSysType());
		List<RolePermissionMappingDO> rolePermissionMappingList = roleService.queryPermissionCodeByPermissionCode(permissionCode);
		//对应用户进行登出处理
		if(!CollectionUtils.isEmpty(rolePermissionMappingList)){
			rolePermissionMappingList.stream().forEach(rolePermissionMappingDO -> {
				userService.roleChangeUser(rolePermissionMappingDO.getRoleCode(),false);
			});
		}
		//变更日志
		PermissionDO afterPermissionDO = BeanUtil.copyProperties(permissionDO, PermissionDO.class);
		afterPermissionDO.setDeleteFlag(Boolean.TRUE);
		//变更日志
		businessChangeLog(permissionDO,afterPermissionDO);
		return CommonResult.success();
	}
	/**
	 * log object
	 *
	 * @param beforeOrganization
	 * @param afterOrganization
	 * @return
	 */
	void businessChangeLog(PermissionDO beforeOrganization, PermissionDO afterOrganization) {
		businessLogService.addBusinessChangeLog(beforeOrganization.getCode(),
				AdminUserEnum.CHANGE_LOG_TYPE.PERMISSION.getCode(),
				CommonEnum.CHANGE_LOG_MODEL_TYPE.ADMIN,
				beforeOrganization,
				afterOrganization);
	}
}
